﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Linq.Expressions;

namespace Whoever.Framework.Reflection
{
    public struct Argument
    {
        public string TypeName;
        public object Value;
    }

    public class ExpressionTreeMethodCall
    {
        public string MethodName { get; set; }
        public IList<Argument> Arguments { get; set; }

        public ExpressionTreeMethodCall()
        {
            Arguments = new List<Argument>();
        }

        public static Action<T> ConvertExpressionTreeMethodToDelegate<T>(ExpressionTreeMethodCall methodData)
        {
            ParameterExpression type = Expression.Parameter(typeof(T));

            var arguments = new List<ConstantExpression>();
            var argumentTypes = new List<Type>();

            foreach (var a in methodData.Arguments)
            {
                arguments.Add(Expression.Constant(a.Value));
                argumentTypes.Add(Type.GetType(a.TypeName));
            }

            // Creating an expression for the method call and specifying its parameter.
            MethodCallExpression methodCall = Expression.Call(type, typeof(T).GetMethod(methodData.MethodName, argumentTypes.ToArray()), arguments);

            return Expression.Lambda<Action<T>>(methodCall, new[] { type }).Compile();
        }

    }
}
